在飲料魔法學院裡,每一個元件(Component)都不是靜止的存在。
它們誕生於魔法師的召喚(onMounted
),在運行中感受能量波動(watch
/ watchEffect
),
最後在結束時歸於靜寂(onUnmounted
)。
這些過程合稱為「Vue 的生命週期(Lifecycle Hooks)」,
是每一位前端魔法師必須熟記的法術節奏。
今天的學習目標是──
讓我們不只是寫出「會動」的元件,
而是能理解「它何時開始運作、何時該停止魔力」的節奏。
使用者 | 需求 | 原因 |
---|---|---|
前端工程師 | 想在元件出現時載入資料 | 若放錯時機(如 beforeMount),可能造成畫面閃爍或資料錯亂 |
前端工程師 | 想監控資料變化、更新畫面 | 若監聽不當,可能導致效能下降或重複請求 |
前端工程師 | 想在頁面離開時清除監聽器或計時器 | 若未清除,可能產生記憶體洩漏或異常錯誤 |
🧙 魔法原則:「每一段魔法都應該有開啟與關閉的時刻」
若你只學會召喚,卻忘記解除,那就是不完全的魔法師。
生命週期就像元件的呼吸與心跳。
若你在錯誤的時間點執行請求、操作 DOM 或監聽事件:
watch
寫錯會導致無限循環或效能暴衝setup() — 魔力的源頭
宣告 reactive / ref、注入 store,設定所有初始能量。
→ 此時元件尚未渲染,但狀態樹已生成。
onBeforeMount — 魔力聚集
DOM 尚未出現在畫面中。可以在這裡做最後預備或初始判斷。
onMounted — 魔力實體化
元件正式出現在頁面上!這時候才能安全地操作 DOM、呼叫 API、啟動監聽。
onBeforeUpdate / onUpdated — 魔力流動與再結構
資料改變 → 頁面要重新渲染。
在 onBeforeUpdate
先暫停舊能量(如清除動畫),
在 onUpdated
再重新開啟(例如重啟動畫或更新視覺效果)。
onBeforeUnmount / onUnmounted — 魔法的歸寂
元件即將消失,釋放所有監聽器、計時器與全域綁定,
否則殘留的魔力(setInterval、window 事件)可能導致錯誤或記憶體洩漏。
💡 這張圖的重點是:「State 隨生命週期的變化流動」
你不只是知道函式何時執行,而是理解資料與 DOM 的「生滅節奏」。
階段 | 說明 | 常見用途 |
---|---|---|
setup() |
組件建立時執行一次 | 初始化變數、注入 store |
onBeforeMount |
元件準備掛載 | seldom 使用(預備階段) |
onMounted |
元件已插入 DOM | 發 API、啟動監聽或動畫 |
onBeforeUpdate |
重新渲染前 | 停止計時、保存狀態 |
onUpdated |
DOM 更新完成 | DOM 依賴更新後動作 |
onBeforeUnmount |
元件卸載前 | 清除計時或監聽 |
onUnmounted |
元件銷毀完成 | 記錄離場事件、釋放資源 |
我們以一個小元件「任務觀測水晶」為例,
它會在誕生時載入任務、在過程中監看變化、最後清除魔法能量。
今天我們就以輕鬆的角度來看vue的生命週期
<script setup>
import { ref, onMounted, onUnmounted, watchEffect } from 'vue'
const tasks = ref([])
const loading = ref(true)
let intervalId = null
// 召喚階段:載入初始資料
onMounted(() => {
console.log(' onMounted: 任務觀測水晶啟動')
loadTasks()
// 每 5 秒刷新資料
intervalId = setInterval(loadTasks, 5000)
})
// 👁 持續觀測能量流動
watchEffect(() => {
if (tasks.value.length > 5) {
console.log(' 偵測到任務過多,請儘快處理!')
}
})
// 🌫 結界解除階段
onUnmounted(() => {
console.log(' onUnmounted: 清除計時器與魔力痕跡')
clearInterval(intervalId)
})
function loadTasks() {
loading.value = true
setTimeout(() => {
// 模擬 API 載入
tasks.value = [
{ id: 1, name: '調配草莓拿鐵' },
{ id: 2, name: '修復冰魔法陣' },
{ id: 3, name: '訓練新學徒' },
]
loading.value = false
}, 800)
}
</script>
<template>
<div class="task-crystal">
<h3>任務觀測水晶</h3>
<p v-if="loading"> 正在觀測任務流...</p>
<ul v-else>
<li v-for="task in tasks" :key="task.id">
{{ task.name }}
</li>
</ul>
</div>
</template>
<style scoped>
.task-crystal {
border: 2px solid #a78bfa;
border-radius: 12px;
padding: 1em;
background: #faf5ff;
}
</style>
階段 | 動作 | 對應程式 |
---|---|---|
onMounted | 初始任務載入、開啟定時刷新 | loadTasks() 、setInterval() |
watchEffect | 偵測任務變化、即時回報 | watchEffect(() => {...}) |
onUnmounted | 清除資源、停止監聽 | clearInterval(intervalId) |
建議修煉方向:
onUnmounted
解除。emit
或 Pinia
讓狀態同步,而不是直接操作 DOM。onBeforeUpdate
、onUpdated
,觀察畫面更新時的節奏。今日成就解鎖
你學會了「Vue 的呼吸術」,
讓每個元件都能在正確的時間呼吸、觀測與歸靜。
今天算是一個過度,但是重要的章節
因為一個程式或是套件的生命週期特別重要
你才會知道他在哪邊呼叫或是使用~
必秒造成問題~
今天的概念學習完後我們就可以規劃最後一章的內容了(主要是會補實戰的一些技巧vue CICD config或是i18n)